/***************************************************************
|	File:		Vector3.cpp
|	Author:		Michael Mozdzierz
|	Date:		05/24/2014
|
***************************************************************/

#include "stdafx.h"
#include "Vector3.h"
#include "Vector2.h"
#include <math.h>
#include <memory>

#pragma region Constructors
Vector3::Vector3(void)
{
	memset(this, 0, 16/*4 bytes x 4 floats = 16 bytes*/);
}
Vector3::Vector3(float x, float y, float z)
{
	this->x = x;
	this->y = y;
	this->z = z;
}

Vector3::Vector3(Vector2& v, float z)
{
	this->x = v.x;
	this->y = v.y;
	this->z = z;
}
#pragma endregion

#pragma region Unary operators
Vector3& Vector3::operator-()
{
	x = -x;
	y = -y;
	z = -z;
	
	return *this;
}
Vector3& Vector3::operator += (Vector3& other)
{
	x += other.x;
	y += other.y;
	z += other.z;

	return *this;
}
Vector3& Vector3::operator -= (Vector3& other)
{
	x -= other.x;
	y -= other.y;
	z -= other.z;

	return *this;
}
#pragma endregion

#pragma region Binary operators

Vector3 operator +(Vector3& a, Vector3& b)
{
	return Vector3(a.x + b.x, a.y + b.y, a.z + b.z);
}
Vector3 operator -(Vector3& a , Vector3& b)
{
	return Vector3(a.x - b.x, a.y - b.y, a.z - b.z);
}
float operator *(Vector3& a, Vector3& b)
{
	return a.x * b.x + a.y * b.y + a.z * b.z;
}
Vector3 operator* (float f, Vector3& v)
{
	return Vector3(v.x * f, v.y * f, v.z * f);
}
Vector3 operator* (Vector3& v, float f)
{
	return Vector3(v.x * f, v.y * f, v.z * f);
}
Vector3 operator /(Vector3& v, float f)
{
	return Vector3(v.x / f, v.y / f, v.z / f);
}
Vector3 operator /(float f, Vector3& v)
{
	return Vector3(v.x / f, v.y / f, v.z / f);
}
#pragma endregion

void Vector3::Normalize(void)
{
	float length = GetLength();

	x /= length;
	y /= length;
	z /= length;
}


float Vector3::GetLength(void) const
{
	return sqrt((x * x) + (y * y) + (z * z));
}

/*static*/ Vector3 Vector3::Cross(Vector3& a, Vector3& b)
{
	float i = a.z * b.y + a.y * b.z;
	float j = a.x * b.z + a.z * b.x;
	float k = a.x * b.y + a.y * b.x;

	return Vector3(i, -j, k);
}

/*static*/ Vector3 Vector3::Normalize(Vector3& v)
{
	Vector3 vv = v;
	vv.Normalize();
	return vv;
}

/*static*/ float Vector3::Dot(Vector3& a, Vector3& b)
{
	return a * b;
}

/*static*/ Vector3 Vector3::Zero = Vector3(0.f, 0.f, 0.f);

/*static*/ Vector3 Vector3::Up = Vector3(0.f, 1.f, 0.f);
/*static*/ Vector3 Vector3::Down = Vector3(0.f, -1.f, 0.f);
/*static*/ Vector3 Vector3::Left = Vector3(1.f, 0.f, 0.f);
/*static*/ Vector3 Vector3::Right = Vector3(-1.f, 0.f, 0.f);
/*static*/ Vector3 Vector3::Forward = Vector3(0.f, 0.f, 1.f);
/*static*/ Vector3 Vector3::Backward = Vector3(0.f, 0.f, -1.f);